<template>
  <!-- <page-header-wrapper> -->
    <div style="height:100%">
      <audio :src="require('@/assets/audio/tip.mp3')"   ref='tipAideo'>您的浏览器不支持 audio 标签。</audio>
      <a-card  style="height:100%" :bodyStyle="{ padding: '0', height: '100%' }">
        <div class="im">
          <div class="im_head">
            <p class="title">客服 {{identity || '- 等待用户咨询...' | identityHidden}}</p>
            <!-- <p class="close_im" @click="handleCloseChat"></p> -->
            <!-- 0：  1:google   2: -->
            <div>
            <a-tag color="#f50" v-if="channelType==0">
              未知 
            </a-tag>
            <a-tag color="#2db7f5" v-else-if="channelType==1">
              google
            </a-tag>
            <a-tag color="#87d068" v-else-if="channelType==2">
              百度
            </a-tag>

            <a-tag color="#2db7f5" v-if="lang == 'zh-cn'">中文</a-tag>
             <a-tag color="#2db7f5" v-if="lang == 'en-us'">En</a-tag>
            </div>
          </div>
          <div class="im_btn end" @click="end_click" v-if="identity">结束服务</div>
          <div class="im_msg" ref="common_chat_main">
            <div ref="common_chat_main_scroll">
              <div class="load-status" v-if="identity && hasMore">
                <span class="btn-load-msg" @click="Scroll">{{ loading ? '点击加载更多历史消息' : '加载中' }}</span>
              </div>
              <div v-for="(it, i) in msg" :key="i">
                <p class="time" v-if="!(it.contentType == 3 || it.contentType == 0)">{{ it.addTime }}</p>
                <div :class="it.fromType == 1 ? 'kf_box' : it.fromType == 2 ? 'fk_box' : ''">
                  <!-- 客服 -->
                  <template v-if="it.fromType == 1">
                    <template v-if="it.contentType == 1 || it.contentType == 2">
                      <img src="@/assets/kf.png" width="40" height="40" alt="kf" />
                      <div class="msg_box">
                        <template v-if="it.contentType == 2">
                          <img :src="`${baseUrl}/${it.content}`" alt="" width="80px" v-if="it.avart"  @click="handleOpenFile(it.content)"/>
                          <img :src="`${baseUrl}/file1.png`" alt="" width="80px" v-else @click="downloads(it.content)"/>
                        </template>
                        <template v-else>{{ it.content }}</template>
                      </div>
                    </template>
                    <!-- 问题 -->
                    <template v-else-if="it.contentType == 3">
                      <img src="@/assets/kf.png" width="40" height="40" alt="kf" />
                      <div class="msg_box3">
                        <div class="title" v-if="!it.isTrue">{{ setting.platformName }}</div>
                        <ul class="msg_box3_ul">
                          <li v-for="(d, ii) in it.content" :key="ii" @click="liClick(d)">
                            {{ d.name }}
                          </li>
                        </ul>
                      </div>
                    </template>
                    <template v-else>
                      <div class="system_message">
                        <span>{{ it.content }}</span>
                      </div>
                    </template>
                    <div></div>
                  </template>
                  <!-- 访客 -->
                  <template v-else-if="it.fromType == 2">
                    <div class="msg_box">
                      <template v-if="it.contentType == 2">
                        <!-- <img :src="`${baseUrl}/${it.content}`" alt="" width="80px" /> -->
                        <img :src="`${baseUrl}/${it.content}`" alt="" width="80px" v-if="it.avart"  @click="handleOpenFile(it.content)"/>
                        <img :src="`${baseUrl}/file1.png`" alt="" width="80px" v-else @click="downloads(it.content)"/>
                      </template>
                      <template v-else>{{ it.content }}</template>
                    </div>
                    <img src="@/assets/kf2.png" width="40" height="40" alt="kf" />
                  </template>

                  <!-- 系统 -->
                  <template v-else>
                    <div class="system_message">
                      <span>{{ it.content }}</span>
                    </div>
                  </template>
                </div>
              </div>
            </div>
          </div>
          <div class="im_fotter">
            <div class="input-wrapper">
              <textarea
                maxlength="500"
                class="inputContent common_chat_emoji-wrapper-global"
                id="common_chat_input"
                :disabled="identity?false:'disabled'"
                placeholder="请输入,按Enter直接发送消息"
                @paste.stop="inputContent_paste"
                @drop="inputContent_drop"
                @keydown="inputContent_keydown"
                @keyup="inputContent_keydown"
                @mouseup="inputContent_mouseup"
                @mouseleave="inputContent_mouseup"
              ></textarea>
            </div>
            <div>
          <div class="im_fotter_head">
            <div>
              <a-upload
                class="avatar-uploader"
                action=""
                :auto-upload="false"
                :before-upload="beforeUpload"
                :show-upload-list="false"
              >
                <img src="@/assets/photo.png" width="28" height="28" alt="" />
              </a-upload>
            </div>
            <div class="right-btn">
              <span @click="(e)=>sendMsg()">发送</span>
            </div>
          </div>
        </div>
          </div>
        </div>
      </a-card>
    </div>
  <!-- </page-header-wrapper> -->
</template>

<script>
import aes from '@/utils/aes'
import rsa from '@/utils/rsa'
import { mapGetters } from 'vuex'
import { getServiceSetting, serviceLog } from '@/api/service'
import { uploadForQiniu, isAvart } from '@/utils/qiniu'
import { officialURL } from '@/utils/request'
// import { serviceUpToken } from '@/api/s'

export default {
  data() {
    return {
      // open: false,
      path: process.env.NODE_ENV == 'development' ? `ws://${officialURL}/ws/service` : `wss://${officialURL}/ws/service`,  //正式服
      socket: '',
      va: '',
      msg: [],
      interval: '',
      num: 0,
      type: 1, //1,还没连上websocket，2连上websocket
      adminId: null,
      identity: null,
      listQuery: {
        pageNum: 1,
        pageSize: 10,
      },
      lang: null,
      total: 0,
      scrollTop: 0,
      loading: true,
      hasMore: true,
      // 按钮
      btn_type: 1, // 1人工客服，2结束会话，3结束排队
      setting: {},
      lockReconnect: true,
      channelType:null,
    }
  },
  computed: {
    ...mapGetters({ sKey: 'sKey', token: 'token', baseUrl: 'baseUrl' }),
  },
  mounted() {
    this.getSetting()
    this.init()
    // 初始化
    // this.$refs.common_chat_main.addEventListener('mousewheel', this.Scroll)
    // this.service_log_find_fun();
    // this.auth_status_fun()
  },
  methods: {
    playTip(){
      if(this.$refs['tipAideo']){
        this.$refs['tipAideo'].pause()
        this.$refs['tipAideo'].currentTime = 0
        this.$refs['tipAideo'].play()
      }
    },
    handleOpenFile(content) {
      window.open(`${this.baseUrl}/${content}`);
    },
    downloads(url){
			var xhr = new XMLHttpRequest();
			xhr.open('get', url, true); // 也可以使用POST方式，根据接口
			// 						xhr.setRequestHeader("dis_k",`cb9a62d3796e276f8707318b3c48ed3d`);
			// xhr.setRequestHeader("dis_t",`1617786336`);
			xhr.responseType = "blob"; // 返回类型blob

			xhr.onload = function () {
			  if (this.status === 200) {
				var blob = this.response;
				var reader = new FileReader();

				reader.readAsDataURL(blob); // 转换为base64，可以直接放入a表情href
				reader.onload = function (e) {
				  var a = document.createElement('a');
          let arr = url.split('/')
				  a.download = arr.pop() || ''; //下载文件名
				  a.href = e.target.result;	
				  a.click();
				  window.URL.revokeObjectURL(e.target.result)
				};
			  }
			}; 
			xhr.send();
		},
    getSetting() {
      const that = this
      getServiceSetting().then((res) => {
        console.log(res)
        that.setting = res.data
      })
    },
    auth_status_fun() {
      var that = this
    },
    handleCloseChat() {
      this.$emit('toggle')
    },
    Scroll(e) {
      if (this.total < this.listQuery.pageNum * this.listQuery.pageSize) {
        this.hasMore = false
        return false
      }
      // var size = this.$refs.common_chat_main.scrollTop;
      if (
        // size < 1 &&
        this.hasMore &&
        this.loading
      ) {
        this.listQuery.pageNum++
        this.service_log_find_fun()
      }
    },
    // 获取聊天记录
    service_log_find_fun() {
      var that = this
      console.log(that.identity)
      that.loading = false
      if (!that.identity) {
        console.log(11111)
        return false
      }
      const listQuery = JSON.parse(JSON.stringify(that.listQuery))
      ;(listQuery.identity = that.identity),
        serviceLog(listQuery).then(async (res) => {
          const { common_chat_main_scroll, common_chat_main } = that.$refs
          const beforHeight = common_chat_main_scroll.clientHeight
          const scrollTop = common_chat_main.scrollTop
          let _data = res.data.data
          if(!_data) return false
          _data = typeof(_data) == 'string' ?  JSON.parse(_data) : _data
          
          _data.forEach((v) => {
            if(v.contentType == 0){
              v.content = '客服分配成功'
              that.addMsg(v, -1);
            }else {
              that.addMsg(v, -1);
            }
          })
          that.$nextTick(() => {
            let height = common_chat_main_scroll.clientHeight
            console.log(beforHeight, height)
            common_chat_main.scrollTop = height - beforHeight + scrollTop
          })
          that.total = res.data.total
          that.loading = true
        })
    },
    init: function () {
      let self = this
      if (typeof WebSocket === 'undefined') {
        alert('您的浏览器不支持socket')
      } else {
        let param = {}
        // if (self.identify) param.identity = self.identify
        console.log(param)
        param = aes.Encrypt(JSON.stringify(param), self.sKey)

        // const pathJSon = { token: this.token, param }
        // 实例化socket
        const path = this.path
        this.socket = new WebSocket(
          path + `?param=${param}&token=${aes.Encrypt(this.token + new Date().getTime(), self.sKey)}`
        )
        // 监听socket连接
        this.socket.onopen = this.open
        // 监听socket错误信息
        this.socket.onerror = this.error
        // 监听socket消息
        this.socket.onmessage = this.getMessage
        this.socket.onclose = this.close
      }
    },
    liClick(row) {
      var that = this
      // window.open()
      console.log(row);
    },
    open: function () {
      var that = this
      that.type = 2
      this.interval = setInterval(function () {
        console.log(that.socket, 11111111);
        that.send(JSON.stringify({ action: 'ping' }))
      }, 15 * 1000)
    },
    error: function () {
      this.socket = null;
      clearInterval(this.interval);
      this.reconnect();
    },
    reconnect() {
      const that = this
      // if (that.lockReconnect) return;
      // that.lockReconnect = true;
      that.interval ? clearInterval(that.interval): ''
      that.socket = null
      //没连接上会一直重连，设置延迟避免请求过多
      setTimeout(function() {
          that.init();
          that.lockReconnect = false;
      }, 2000);
    },
    resetUser() {
      ;(this.msg = []), (this.listQuery.pageNum = 1)
      this.total = 0
      this.loading = true
      this.hasMore = true
    },
    getMessage: function (msg) {
      console.log(msg)
      console.log(this)
      var that = this
      var data = JSON.parse(msg.data)
      if (data.action == 'allot') {
        this.playTip()
        that.resetUser()
        let param = data.param
        that.identity = param.identity
        that.adminId = param.adminId
        that.lang = param.lang
        data.param.content = `用户 ${param.identity.substring(0, 5)}...${param.identity.substring(
          param.identity.length - 6,
        )} 已连接`
        this.channelType = param.channelType
        that.service_log_find_fun()
        that.addMsg(data.param)
        that.$nextTick(()=>{
          that.sendMsg(that.lang == 'zh-cn'?that.setting.firstReply:that.setting.firstReplyUs)
        })
        
      } else if (data.action == 'msg') {
        this.playTip()
        console.log(data.action)
        that.addMsg(data.param)
      } else if(data.action == 'unlink'){
        this.identity = null
      }else if(data.action == 'end'){
        this.channelType = null
        this.lang = null
      }
    },
    send: function (params) {
      this.socket.send(params)
    },
    getTime() {
      let date = new Date()
      let year = date.getFullYear()
      let month = (date.getMonth() + 1).toString().padStart(2, '0')
      let day = date.getDate().toString().padStart(2, '0')
      let h = date.getHours().toString().padStart(2, '0')
      let m = date.getMinutes().toString().padStart(2, '0')
      var time = `${year}-${month}-${day} ${h}:${m}`
      return time
    },
    addMsg(params, a_add = 1) {
      const that = this
      const item = {
        content: params.content, // 内容
        contentType: params.contentType || 0, //
        fromType: params.fromType, // 1：客服  2：用户
        addTime: params.addTime || that.getTime(),
      }
      if(item.contentType == 2){
        let contentArr = item.content.split('.');
        let last = contentArr.pop()
        item.avart = isAvart(last)
      }
      if (a_add == 1) {
        this.msg.push(item)
        document.getElementById('common_chat_input').value = ''
        that.$nextTick(() => {
          that.$refs.common_chat_main.scrollTop = that.$refs.common_chat_main.scrollHeight
        })
      } else {
        this.msg.unshift(item)
      }
    },
    close: function (a_bool) {
      console.log('close', a_bool);
      var that = this;
      that.socket.close()
      this.socket = null;
      clearInterval(that.interval);
      if(a_bool){
         this.reconnect();
      }
      // this.btn_type = 1
      // this.msg.push({ contentType: 0, content: '与客服断开连接' })
      // setTimeout(function () {
      //   that.$refs.common_chat_main.scrollTop = that.$refs.common_chat_main.scrollHeight
      // }, 100)
      // if (this.num < 3) {
      //   var data = this.commonData();
      //   this.num++;
      //   this.init(data.key, data.authToken);
      // }
    },
    commonData(string, data) {
      var string = aes.randomString(16)
      var data = {
        key: rsa.RSAencrypt(string),
        authToken: aes.Encrypt(this.$store.getters.token + new Date().getTime(), string),
        // authToken: aes.Encrypt(1, string),
      }
      data.key = this.delStr(data.key)
      data.authToken = this.delStr(data.authToken)
      return data
    },
    delStr(str) {
      str = str
        .replace(/\+/g, '..a,,')
        .replace(/\//g, '..b,,')
        .replace(/\?/g, '..c,,')
        .replace(/\%/g, '..d,,')
        .replace(/\#/g, '..e,,')
        .replace(/\&/g, '..f,,')
        .replace(/\=/g, '..g,,')
      return str
    },
    sendMsg(a_val, a_type = 1, a_action = 'msg') {
      const that = this
      if (!that.socket) return false
      if (!a_val && !that.va) return false
      let parms = {
        adminId: that.adminId,
        content: a_val || that.va,
        fromType: 1,
        identity: that.identity,
        contentType: a_type,
      }
      that.send(
        JSON.stringify({
          action: a_action,
          param: parms,
        })
      )
      that.addMsg(parms)
    },
    /**
     * 设置输入内容
     * 根据input输入框value转换为纯文本
     */
    setInputContentByDiv: function () {
      var self = this
      var htmlStr = document.getElementById('common_chat_input').value

      // 1.转换表情为纯文本：<img textanme="[笑]"/> => [笑]
      var tmpInputContent = htmlStr.replace(/<img .+?text=\"(.+?)\".+?>/g, '[$1]').replace(/<.+?>/g, '')

      // 2.设置最长长度
      if (tmpInputContent.length > 500) {
        document.getElementById('common_chat_input').value = ''
        var value = tmpInputContent.substr(0, 499).replace(/\[(.+?)\]/g, function (item, value) {
          return self.$refs.qqemoji.getImgByFaceName(value)
        })
        this.setInputDiv(value)
      }

      // 3.修改store
      this.va = tmpInputContent
    },
    inputContent_keydown: function (e) {
      // keyup触发时，绑定的数据还没有被变更，需要进行延后访问
      clearTimeout(this.$data.inputContent_setTimeout)
      this.$data.inputContent_setTimeout = setTimeout(() => {
        this.setInputContentByDiv()

        // 若按了回车，直接发送
        if (e.keyCode == 13) {
          this.sendMsg()
        }
        this.setInputContentSelectRange()
      }, 100)
    },
    /**
     * 输入框的mouseup
     */
    inputContent_mouseup: function (e) {
      this.setInputContentSelectRange()
    },
    /**
     * 设置input输入框的选择焦点
     */
    setInputContentSelectRange: function () {
      if (window.getSelection && window.getSelection().rangeCount > 0) {
        var selectRange = window.getSelection().getRangeAt(0)
        if (
          selectRange.commonAncestorContainer.nodeName == '#text' &&
          selectRange.commonAncestorContainer.parentElement &&
          selectRange.commonAncestorContainer.parentElement.id == 'common_chat_input'
        ) {
          // 选中了输入框内的文本
          this.$data.selectionRange = selectRange
        } else if (selectRange.commonAncestorContainer.id == 'common_chat_input') {
          // 选中了输入框
          this.$data.selectionRange = selectRange
        }
      }
    },
    beforeUpload(file, fileList, index) {
      if( !this.socket || !this.identity){
        return false
      }
      this.uploadFun(file)
    },
    uploadFun(a_files) {
      var that = this
      function successCB(res) {
        const param = {
          adminId: that.adminId,
          content: res.key,
          fromType: 1,
          identity: that.identity,
          contentType: 2,
        }
        that.send(JSON.stringify({ action: 'msg', param }))
        that.addMsg(param)
      }
      function errorCB(err) {
        that.$message.error(err)
      }
      uploadForQiniu(a_files, successCB, () => {}, errorCB).then((res) => {})
    },
    /**
     * 输入框的拖拽
     */
    inputContent_drop: function (e) {
      var self = this
      setTimeout(function () {
        self.setInputContentByDiv()
      }, 100)
    },
    /**
     * 输入框的粘贴
     */
    inputContent_paste: function (e) {
      var self = this
      var isImage = false
      if (e.clipboardData && e.clipboardData.items.length > 0) {
        // 1.上传图片
        for (var i = 0; i < e.clipboardData.items.length; i++) {
          var item = e.clipboardData.items[i]
          if (item.kind == 'file' && item.type.indexOf('image') >= 0) {
            // 粘贴板为图片类型
            var file = item.getAsFile()
            self.uploadFun(file)
            isImage = true
          }
        }
        // 2.非图片，粘贴纯文本
        if (!isImage) {
          var str = e.clipboardData.getData('text/plain')
          // 转化为纯文字
          self.va = str
          var span = document.createElement('span')
          span.value = str
          var txt = span.innerText
          this.setInputDiv(txt.replace(/\n/g, '').replace(/\r/g, '').replace(/</g, '&lt;').replace(/>/g, '&gt;'))
        }
      }
      e.stopPropagation()
      e.preventDefault()
    },
    setInputDiv: function (value) {
      if (this.$data.selectionRange == null) {
        document.getElementById('common_chat_input').focus()
        return
      }
      // 1.设置selectionRange
      if (window.getSelection) {
        window.getSelection().removeAllRanges()
        window.getSelection().addRange(this.$data.selectionRange)
      } else {
        this.$data.selectionRange && this.$data.selectionRange.select()
      }

      // 2.表情转换为img

      // 3.聊天框中是否选中了文本，若选中文本将被替换成输入内容
      if (window.getSelection) {
        var sel, range
        // IE9 and non-IE
        sel = window.getSelection()
        if (sel.getRangeAt && sel.rangeCount) {
          // 1)删除选中的文本(内容)
          range = sel.getRangeAt(0) // 获取鼠标选中的文本区域
          range.deleteContents() // 删除选中的文本

          // 2)创建以输入内容为内容的DocumentFragment
          var elemnet
          if (range.createContextualFragment) {
            elemnet = range.createContextualFragment(value)
          } else {
            // 以下代码等同createContextualFragment
            // 创建一个DocumentFragment
            elemnet = document.createDocumentFragment()

            var divEl = document.createElement('div')
            divEl.value = value
            // divEl下的元素，依次插入到DocumentFragment
            for (let i = 0, len = divEl.children.length; i < len; i++) {
              elemnet.appendChild(divEl.firstChild)
            }
          }
          // 3)选中文本的位置替换为新输入的内容，并把光标定位到新内容后方
          var lastNode = elemnet.lastChild
          range.insertNode(elemnet)
          range.setStartAfter(lastNode)
          sel.removeAllRanges()
          sel.addRange(range)
        }
      } else if (document.selection && document.selection.type != 'Control') {
        // IE < 9
        document.selection.createRange().pasteHTML(imgStr)
      }

      // 4.修改inputContent
      this.setInputContentByDiv()
    },
    // 结束按钮
    end_click() {
      var that = this
      console.log(that.setting)

      if (that.socket) {
        let content = (that.lang == 'zh-cn'?that.setting.closeReply : that.setting.closeReplyUs) || ''
        that.sendMsg(content, 1, 'end')
        this.identity = null
        this.channelType = null
        this.lang = null
        // clearInterval(that.interval);
      } else {
        var data = that.commonData()
        that.init(data.key, data.authToken)
      }
    },
  },
  filters:{
    identityHidden: function(str){
      return str.length > 11 ?`(${str.substring(0,5)}...${str.substring(str.length - 5)})` : str
    }
  },
  destroyed() {
    // 销毁监听
    // this.$refs.common_chat_main.removeEventListener('mousewheel', this.Scroll)
    this.close(false)
  },
}
</script>
<style lang='less'>
.im_fotter_head {
  .avatar-uploader .el-upload {
    width: 28px;
    height: 28px;
    border: none;
  }
}
</style>
<style scoped lang="less">
@import './index.less';
.a{
  display: block;
  align-items:stretch
}
</style>